#pragma once
#include "mq_channel.hpp"

namespace mymq
{
    class Connection
    {
    public:
        using Ptr = std::shared_ptr<Connection>;
        Connection( const muduo::net::TcpConnectionPtr &conn,
                           const ProtobufCodecPtr &code,
                           const mymq::ConsumerManager::Ptr &cmp,
                           const VirtualHost::Ptr &host,
                           const Threadpool::Ptr &pool)
                           :_conn(conn),
                           _code(code),
                           _cmp(cmp),
                           _pool(pool),
                           _host(host),
                           _channels(std::make_shared<ChannelManager>())
        {}
        //针对这个打开的请求进行响应处理
        void OpenChannel(const openChannelRequestPtr &req)
        {
            //判断该信道是否已经存在，不存在即创建
            bool ret = _channels->OpenChannel(req->cid(),_conn,_code,_cmp,_host,_pool);
            if(ret == false)
            {
                return basicResponse(false,req->rid(),req->cid());
            }
            //返回创建成功的响应
            return basicResponse(true,req->rid(),req->cid());
        }
        void CloseChannel(const closeChannelRequestPtr &req)
        {
            _channels->CloseChannel(req->cid());
            return basicResponse(true,req->rid(),req->cid());
        }
        Channel::Ptr GetChannel(const std::string &cid)
        {
            return _channels->GetChannel(cid);
        }
    private:
        // 通用响应
        void basicResponse(bool ok, const std::string &rid, const std::string &cid)
        {
            basicCommonResponse resp;
            resp.set_rid(rid);
            resp.set_cid(cid);
            resp.set_ok(ok);
            _code->send(_conn, resp);
        }
    private:
        muduo::net::TcpConnectionPtr _conn; // 网络通信协议
        ProtobufCodecPtr _code;             // 协议处理
        VirtualHost::Ptr _host;             // 虚拟机句柄
        mymq::ConsumerManager::Ptr _cmp;    // 消费者管理句柄
        Threadpool::Ptr _pool;              // 线程池
        ChannelManager::Ptr _channels;
    };

    class ConnectionManager
    {
    public:
        using Ptr = std::shared_ptr<ConnectionManager>;
        ConnectionManager(){}
        //添加连接
        bool AddConnection(const muduo::net::TcpConnectionPtr &conn,
                           const ProtobufCodecPtr &code,
                           const mymq::ConsumerManager::Ptr &cmp,
                           const VirtualHost::Ptr &host,
                           const Threadpool::Ptr &pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            //先查找是否已经存在该链接
            auto it = _conns.find(conn);
            if(it != _conns.end())
            {
                DLOG("创建失败，已经存在该连接");
                return false;
            }
            //创建连接
            auto self_cmp = std::make_shared<Connection>(conn,code,cmp,host,pool);
            if(self_cmp.get()==nullptr)
            {
                DLOG("创建连接失败");
                return false;
            }
            _conns.insert(std::make_pair(conn,self_cmp));
            return true;
        }
        //删除/关闭连接
        void DeleteConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end())
            {
                DLOG("删除失败，未找到该连接");
                return;
            }
            _conns.erase(conn);
        }
        Connection::Ptr GetConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end())
            {
                DLOG("获取该连接失败，未找到该连接");
                return Connection::Ptr();
            }
            return it->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr,Connection::Ptr> _conns;
    };
}